﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTree.Stalk.Roots.Database;
using TechTree.Stalk.Roots.Databases.Odbc;
using TechTree.Stalk.Roots.Databases.OleDb;
using TechTree.Stalk.Roots.Databases.Oracle;
using TechTree.Stalk.Roots.Databases.SQLServer;
using TechTree.Stalk.Roots.Exceptions;

namespace TechTree.Stalk.Roots.Databases.Factories
{
    public class DatabaseContextFactory
    {
        #region Constantes
        #region PROVIDER NAMES
        private const string SUPPORTED_ORACLE_SERVER_PROVIDER_NAME = "oracle.dataaccess.client";
        private const string SUPPORTED_SQL_SERVER_PROVIDER_NAME = "system.data.sqlclient";
        private const string SUPPORTED_OLE_DB_CONNECTION_PROVIDER_NAME = "system.data.oledb";
        private const string SUPPORTED_ODBC_CONNECTION_PROVIDER_NAME = "system.data.odbc";
        #endregion
        #region ERROR_MESSAGES
        private const string UNSUPPORTED_PROVIDER_EMPTY_PROVIDER_NAME = "Cannot create provider. The provider name is null or empty.";
        private const string UNSUPPORTED_PROVIDER_NAME_ERROR_MESSAGE = "The provider '{0}' is not supported. Please see system documentation for more information.";
        private const string CREATING_DATABASE_CONTEXT_ERROR_MESSAGE = "Error while creating database context with connection string '{0}'. Message: '{1}'.";
        #endregion
        #endregion

        private DatabaseContextFactory() { }

        public static DatabaseContext CreateDatabaseContext(string connectionStringKey)
        {
            try
            {
                ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringKey];
                DatabaseContext databaseContext = null;

                switch (connectionStringSettings.ProviderName.ToLower())
                {
                    case (SUPPORTED_ORACLE_SERVER_PROVIDER_NAME):
                        {
                            databaseContext = new OracleDatabaseContext(connectionStringSettings.ConnectionString);
                            break;
                        }
                    case (SUPPORTED_SQL_SERVER_PROVIDER_NAME):
                        {
                            databaseContext = new SQLServerDatabaseContext(connectionStringSettings.ConnectionString);
                            break;
                        }
                    case (SUPPORTED_OLE_DB_CONNECTION_PROVIDER_NAME):
                        {
                            databaseContext = new OleDbDatabaseContext(connectionStringSettings.ConnectionString);
                            break;
                        }

                    case (SUPPORTED_ODBC_CONNECTION_PROVIDER_NAME):
                        {
                            databaseContext = new OdbcDatabaseContext(connectionStringSettings.ConnectionString);
                            break;
                        }
                    default:
                        {
                            if (String.IsNullOrEmpty(connectionStringSettings.ProviderName.ToLower()))
                            {
                                throw new NotSupportedException(UNSUPPORTED_PROVIDER_EMPTY_PROVIDER_NAME);
                            }
                            throw new NotSupportedException(String.Format(UNSUPPORTED_PROVIDER_NAME_ERROR_MESSAGE, connectionStringSettings.ProviderName));
                        }
                }

                return databaseContext;
            }
            catch (Exception excep)
            {
                throw new DataAccessLayerException(String.Format(CREATING_DATABASE_CONTEXT_ERROR_MESSAGE, connectionStringKey, excep.Message));
            }
        }
    }
}
